#include "def.h"
#include "lib0.h"

void memset(void *b, int c, long len)
{
    unsigned char *p;
    for (p = b; len > 0; len--)
        *p++ = c;
}

void memcpy(void *dst, const void *src, long len)
{
    const char *s = src;
    char *d = dst;
    for ( ; len > 0; len--)
        *d++ = *s++;
}

int memcmp(const void *b1, const void *b2, long len)
{
    const unsigned char *p1 = b1, *p2 = b2;
    for (; len > 0; len--, p1++, p2++) {
        if (*p1 != *p2)
            return *p1 - *p2;
    }
    return 0;
}

int memeq(const void *mem, unsigned char c, long len)
{
    const unsigned char *p = mem;
    while (len-- > 0) {
        if (*p++ != c)
            return 0;
    }
    return 1;
}

int strlen(const char *s)
{
    int len;
    for (len = 0; *s; len++, s++)
        ;
    return len;
}

void strcpy(char *dst, const char *src)
{
    for (; ; dst++, src++) {
        *dst = *src;
        if (!*src)
            return;
    }
}

int strcmp(const char *s1, const char *s2)
{
    const unsigned char *p1 = (const unsigned char *)s1, *p2 = (const unsigned char *)s2;
    for (; *p1 || *p2; p1++, p2++) {
        if (*p1 != *p2)
            return *p1 - *p2;
    }
    return 0;
}

int strncmp(const char *s1, const char *s2, int len)
{
    const unsigned char *p1 = (const unsigned char *)s1, *p2 = (const unsigned char *)s2;
    for (; len > 0 && (*p1 || *p2); len--, p1++, p2++) {
        if (*p1 != *p2)
            return *p1 - *p2;
    }
    return 0;
}

static void reverse(char s[], int len)
{
    if (len > 1) {
        char *p = &s[len - 1];
        for (; s < p; s++, p--) {
            char tmp = *s;
            *s = *p;
            *p = tmp;
        }
    }
}

int ltos(unsigned long value, char *buf)
{
    int len = 0;

    do {
        unsigned short r;
        value = div3216(value, 10, &r);
        buf[len++] = '0' + r;
    } while (value);

    reverse(buf, len);
    buf[len] = '\0';

    return len;
}

int xtos(unsigned long value, char *buf)
{
    int len = 0;

    do {
        buf[len++] = "0123456789abcdef"[value & 0xf];
        value >>= 4;
    } while (value);

    reverse(buf, len);
    buf[len] = '\0';

    return len;
}

int atoi(const char *s)
{
    int r = 0, neg = 0;

    for (; *s == ' '; s++)
        ;

    if (*s == '-') {
        neg = 1;
        s++;
    } else if (*s == '+') {
        s++;
    }

    for (; '0' <= *s && *s <= '9'; s++) {
        r = r * 10 + (*s - '0');
    }

    return neg ? -r : r;
}

long atol(const char *s)
{
    int neg = 0;
    long r = 0;

    for (; *s == ' '; s++)
        ;

    if (*s == '-') {
        neg = 1;
        s++;
    } else if (*s == '+') {
        s++;
    }

    for (; '0' <= *s && *s <= '9'; s++) {
       r = r * 10 + (*s - '0');
    }

    return neg ? -r : r;
}

unsigned long xtol(const char *s)
{
    unsigned long ret = 0;

    while (*s == ' ')
        s++;

    if (*s == '0' && *(s+1) == 'x')
        s += 2;

    for(;;s++) {
        char c = *s;

        if ('0' <= c && c <= '9') {
            ret = (ret << 4) + (c - '0');
        } else if ('A' <= c && c <= 'F') {
            ret = (ret << 4) + (c - 'A' + 10);
        } else if ('a' <= c && c <= 'f') {
            ret = (ret << 4) + (c - 'a' + 10);
        } else {
            break;
        }
    }

    return ret;
}

// [+-]?[0-9]+
int is_num(const char *s)
{
    if (*s == '-' || *s == '+')
        s++;

    do {
        if (!('0' <= *s && *s <= '9'))
            return 0;
    } while (*++s);

    return 1;
}

// (0x)?[0-9A-Fa-f]+
int is_xnum(const char *s)
{
    if (*s == '0' && *(s+1) == 'x')
        s += 2;

    do {
        if (!('0' <= *s && *s <= '9') && !('A' <= *s && *s <= 'F') && !('a' <= *s && *s <= 'f'))
            return 0;
    } while (*++s);

    return 1;
}

char *getarg(char **pp)
{
    char *p = *pp;
    char *q;

    while (*p == ' ') p++;
    if (*p == '\0') { *pp = p; return NULL; }
    q = p;
    while (*p != ' ' && *p != '\0') p++;
    if (*p == ' ') *p++ = '\0';

    *pp = p;
    return q;
}
